/*
 * app_file_packet_api.c
 *
 *  Created on: 2023年8月25日
 *      Author: HXF
 */

#include "stdlib.h"
#include "app_broadcast_retry.h"
#include "app_filetransport_api.h"
#include "app_filetransport_api_subsidiary.h"
#include "app_log.h"
#ifdef HUB_DEVICE
#include "app_hub_api_rf_event.h"
#include "app_hub_api_subsidiary.h"
#else
#include "app_key_value.h"
#endif

#ifdef HUB_DEVICE
int production_broadcast_notify(void)
{
  //同步广播 UpdateMe物模型
  filetransport_msg_t pkt = {0};
  unsigned char updateme_id_num = 0;
  unsigned char bcast_busy = 0;

  getThisParam(ENbyOtaUpdatemeIDNum, &updateme_id_num);
  getThisParam(ENbyBcastBusy, (unsigned char *)&bcast_busy);

  if(updateme_id_num){
      getThisParam(ENbyOtaUpdatemeID, pkt.data.production_broadcast_notify_payload.id);
  }else{
      return -1;
  }

  if(bcast_busy){ //OTA前正在发同步广播，不触发广播通知
      return -2;
  }

  //组文件传输notify报文
  pkt.data.production_broadcast_notify_payload.bretry = FILE_TRANSPORT_RETRY_COUNT;
  pkt.data.production_broadcast_notify_payload.btype = 0x08;
  pkt.data.production_broadcast_notify_payload.len = 1 + updateme_id_num; //ctrl + id[]
  pkt.data.production_broadcast_notify_payload.ctrl = 0xF0; //0xf0:广播升级

  DS_hub_api_creat_rf_sync_broadcast_event((unsigned char *)pkt.data.data,
                                           (pkt.data.production_broadcast_notify_payload.len+3));
  return 0;
}

int production_qrfh_notify(void)
{
  unsigned char updateme_id_num = 0;
  unsigned char updateme_id[OTA_ID_BUF_MAX] = {0};
  unsigned char qrfh2 = 0;

  getThisParam(ENbyOtaUpdatemeIDNum, &updateme_id_num);

  if(updateme_id_num){
      getThisParam(ENbyOtaUpdatemeID, updateme_id);
  }else{
      return -1;
  }
  for(int i = 0; i < updateme_id_num; i++){
      getDeviceParam(updateme_id[i], ENpbyNodeQrfH2First, &qrfh2);
      (qrfh2 |= (1 << 0));   //isFileTx 置1
      setDeviceParam(updateme_id[i], ENpbyNodeQrfH2First, &qrfh2);
  }
  start_qrfh_handshake_Timer();
  return 0;
}

int production_consult_request(unsigned char rfmid)
{
  unsigned char flag = 1;
  setDeviceParam(rfmid, ENbyOtaConSultFlag, &flag);
  return 0;
}

int production_page_filetransport(unsigned char *ptr_netpkt, int *payload_len)
{
  unsigned char read_link_idx = 0;
  unsigned char blockid = 0;
  cache_page_file_t page_msg = {0};
  int page_msg_len = 0;

  *payload_len = 0;
  if(!ptr_netpkt){
      return -1;
  }
#if(1)
  getThisParam(ENbyReadFileLinkIdx, &read_link_idx);
  if(file_cache_link_is_empty(read_link_idx)){
      return 1;
  }

  if(file_cache_link_pop(read_link_idx, (unsigned char *)&page_msg, &page_msg_len) == 0){
      ota_update_custom_progress();
      ota_custom_cache_history(read_link_idx, (unsigned char *)&page_msg, page_msg_len);
      *payload_len = (page_msg.data_len + 6);
      memcpy(ptr_netpkt, &page_msg.page_id[0], *payload_len);
  }
  blockid = get_blockid_by_pageid(page_msg.page_id);
  if(read_link_idx == FILE_LINK_1 || read_link_idx == FILE_LINK_2){
      set_ota_production_file_link_custom_blockid(blockid);
      if(file_log_enable){
          APP_PRINTF("tr bid %d\r\n",blockid);
      }
  }else{
      if(file_log_enable){
          APP_PRINTF("tr history\r\n");
      }
  }
#else
  for(int i = 0; i < 10; i++)
    ptr_netpkt[i] = 0xa0+i;
  *payload_len = 10;
#endif
  return 0;
}

int production_check_request(unsigned char *ptr_netpkt, int *payload_len)
{
  filetransport_msg_t pkt = {0};
  unsigned char updateme_id_num = 0;

  *payload_len = 0;
  if(!ptr_netpkt){
      return -1;
  }
  getThisParam(ENbyOtaUpdatemeIDNum, &updateme_id_num);
  if(updateme_id_num){
      getThisParam(ENbyOtaUpdatemeID, pkt.data.production_check_request_payload.id);
  }else{
      return -1; //全部被删除了
  }
  getThisParam(ENpbySystemID, &pkt.data.production_check_request_payload.system_id);
  pkt.data.production_check_request_payload.bretry = FILE_TRANSPORT_RETRY_COUNT;
  pkt.data.production_check_request_payload.btype = 0x08;
  pkt.data.production_check_request_payload.len = 1 + updateme_id_num;
  pkt.data.production_check_request_payload.ctrl = 0xF1;

  *payload_len = (pkt.data.production_check_request_payload.len + 6);
  memcpy(ptr_netpkt, &pkt.data.production_check_request_payload.system_id[0], *payload_len);
  return 0;
}

int production_deal_transport_request_keyvalue(unsigned char rfmid,
                                               const unsigned char *value, int value_len)
{
  if(!value || value_len == 0){
      return -1;
  }
  //当前不处于握手阶段，不处理该物模型
  FILE_TRANSPORT_E step;
  step = get_file_transport_step();
  if(step != PRODUCTION_HANDSHAKE){
      return 4;
  }

  //0xff物模型 len+ftype+info
  if(value_len != value[0]+1){
      if(file_log_enable){
          DS_app_log_error("request len not match\n");
      }
      return 3;
  }

  if(update_ota_rfm_request_state(rfmid, 1) == 0){
      production_consult_request(rfmid);  //0xFE文件传输接受物模型 flag置1
  }
  return 0;
}

__attribute__((weak)) void stop_ota_broadcast_retry_timer(void)
{

}

int production_deal_transport_confirm_keyvalue(unsigned char rfmid,
                                               const unsigned char *value, int value_len)
{
  if(!value || value_len == 0){
      return -1;
  }
  //当前不处于握手阶段，不处理该物模型
  FILE_TRANSPORT_E step;
  step = get_file_transport_step();
  if(step != PRODUCTION_HANDSHAKE){
      return 4;
  }

  //0xfd物模型 len+ftype+info
  if(value_len != value[0]+1){
      if(file_log_enable){
          DS_app_log_error("confirm len not match\n");
      }
      return 3;
  }

  if(update_ota_rfm_confirm_state(rfmid, 1) == 0){
      if(check_ota_rfm_all_confirm() && check_ota_rfm_all_request()){
          //全部待OTA rfm握手完成
          stop_ota_broadcast_retry_timer();
          stop_qrfh_handshake_Timer();
          creat_ota_wait_finish_event();
      }
  }
  return 0;
}

int production_deal_check_result_keyvalue(unsigned char rfmid,
                                               const unsigned char *keyvalue, int len)
{
  if(!keyvalue || len == 0){
      return -1;
  }

  //0xfb物模型 len+data
  if(len != (keyvalue[0]+1)){
      if(file_log_enable){
          DS_app_log_error("len not match\n");
      }
      return 3;
  }

  if(update_ota_rfm_check_state(rfmid, 1,
                                (unsigned char *)&keyvalue[1], keyvalue[0]) == 0){
      if(check_ota_rfm_all_check()){
          stop_ota_broadcast_retry_timer();
          creat_ota_wait_finish_event();
      }
  }
  return 0;
}

#endif

#ifdef RFM_DEVICE
int consumption_request(void)
{
  filetransport_msg_t pkt = {0};
  unsigned char flag = 0;
  //0xff物模型 cmd 0x04实时上报
  pkt.data.consumption_request_payload.len = OTA_REQUEST_KEYVALUE_INFO_LENGTH + 1;
  pkt.data.consumption_request_payload.ftype = FTYPE_OTA;
  getThisParam(ENbyDeviceType, &pkt.data.consumption_request_payload.info[0]);
  getThisParam(ENbyModelType, &pkt.data.consumption_request_payload.info[1]);
  getThisParam(ENbyHardType, &pkt.data.consumption_request_payload.info[2]);
  getThisParam(ENpbyMacID, &pkt.data.consumption_request_payload.info[3]); //3-10
  getThisParam(ENpbyRfVer, &pkt.data.consumption_request_payload.info[11]);//11-13
  getThisParam(ENpbySensorVer, &pkt.data.consumption_request_payload.info[14]);//14-16

  //填0xff 文件传输物模型
  setThisParam(ENbyOtaRequestKeyValue, &pkt.data.consumption_request_payload.len);
  setThisParam(ENbyOtaRequestFlag, &flag); //等到超时定时器时间到了,推送给物模型队列
  return 0;
}

int consumption_confirm(void)
{
  filetransport_msg_t pkt = {0};
  unsigned char flag = 0;
  //0xfd物模型 cmd 0x04实时上报
  pkt.data.consumption_confrim_payload.len = OTA_CONFIRM_KEYVALUE_INFO_LENGTH + 1;
  pkt.data.consumption_confrim_payload.ftype = FTYPE_OTA;
  getThisParam(ENbyDeviceType, &pkt.data.consumption_confrim_payload.info[0]);
  getThisParam(ENbyModelType, &pkt.data.consumption_confrim_payload.info[1]);
  getThisParam(ENbyHardType, &pkt.data.consumption_confrim_payload.info[2]);
  getThisParam(ENpbyMacID, &pkt.data.consumption_confrim_payload.info[3]); //3-10
  getThisParam(ENpbyRfVer, &pkt.data.consumption_confrim_payload.info[11]);//11-13
  getThisParam(ENpbySensorVer, &pkt.data.consumption_confrim_payload.info[14]);//14-16

  //填0xfd 文件传输物模型
  setThisParam(ENbyOtaConfirmKeyValue, &pkt.data.consumption_confrim_payload.len);
  setThisParam(ENbyOtaConfirmFlag, &flag); //等到超时定时器时间到了,推送给物模型队列
  return 0;
}

int consumption_check_response(void)
{
  return 0;
}

int consumption_deal_qrfh2(unsigned char qrfh2)
{

  unsigned char file_type = 0;
  keyValue_t kv = {0};
  FILE_TRANSPORT_E step;
  unsigned char isFileTx = 0;

  isFileTx = (qrfh2 & 0x01);
  step = get_file_transport_step();
  switch(step){
    case NO_TRANSPORT:
      if(isFileTx == 1){
          file_type = FTYPE_OTA;
          setThisParam(ENbyTransFileType, &file_type);     //传输类型

          ota_enter_hook();
          consumption_request(); //组文件传输物模型

          kv.id = 0xff;
          kv.valueSize = OTA_REQUEST_VALUE_LENGTH;
          getThisParam(ENbyOtaRequestKeyValue, &kv.value);
          set_key_value(&kv);

          start_timer_to_check_no_rcv_timeout();
      }
      break;
    default:
      break;
  }

  return 0;
}

int consumption_deal_sync_broadcast_updateme_keyvalue(const unsigned char *keyvalue, int len)
{
  if(!keyvalue || len == 0){
      return -1;
  }

  //UPDATEME物模型 ctrl id[]

  unsigned char rfmid = 0;
  unsigned char updateme_id_num = 0;
  unsigned char i = 0;
  unsigned char file_type = 0;
  unsigned char updateme_id[OTA_ID_BUF_MAX] = {0};
  keyValue_t kv = {0};
  char msg[2] = {0};
  FILE_TRANSPORT_E step;

  step = get_file_transport_step();
  switch(step){
    case NO_TRANSPORT:
    case CONSUMPTION_REQUEST: //如果HUB没有收到请求，rfm收到固件广播时，还停在该阶段
      break;
    default:
      return 4;
      break;
  }

  if(keyvalue[0] == 0xf0){  //ctrl 0xf0,固件广播升级
      file_type = FTYPE_OTA;
      updateme_id_num = len - 1;
      if(updateme_id_num == 0){
          if(file_log_enable){
              DS_app_log_error("no id buf\n");
          }
          return 4;
      }else{
          if(updateme_id_num > OTA_ID_BUF_MAX){
              if(file_log_enable){
                  DS_app_log_error("id too much\n");
              }
              return 5;
          }
      }
      getThisParam(ENpbyRfmId, &rfmid);
      for(i = 0; i < updateme_id_num; i++){
          if(keyvalue[1+i] == rfmid){
              break;
          }
      }
      if(i == updateme_id_num){
          //没有找到，不在列表里。不处理
      }else{
          memcpy(updateme_id, &keyvalue[1], updateme_id_num);
          setThisParam(ENbyTransFileType, &file_type);     //传输类型
          setThisParam(ENbyOtaUpdatemeID, updateme_id);      //ota ID[]
          setThisParam(ENbyOtaUpdatemeIDNum, &updateme_id_num);     //ota ID长度

          ota_enter_hook();
          consumption_request(); //组文件传输物模型

          if(updateme_id_num == 1){
              kv.id = 0xff;
              kv.valueSize = OTA_REQUEST_VALUE_LENGTH;
              getThisParam(ENbyOtaRequestKeyValue, &kv.value);
              set_key_value(&kv);
          }else{
              msg[0] = 1;
              msg[1] = 0xf0;
              start_timer_to_trigger_updateme_response(msg, 2, NULL);
          }

          start_timer_to_check_no_rcv_timeout();
      }
  }
  return 0;
}

int consumption_deal_consult_keyvalue(const unsigned char *keyvalue, int len)
{
  if(!keyvalue || len == 0){
      return -1;
  }
  keyValue_t kv = {0};
  unsigned char data[OTA_CONSULT_KEYVALUE_LENGTH] = {0};
  FILE_TRANSPORT_E step;
  int iret = 0;

  step = get_file_transport_step();
  if(step != CONSUMPTION_REQUEST){
      return 4;
  }

  //0xfe物模型 len+data
  if(len != (keyvalue[0]+1)){
      if(file_log_enable){
          DS_app_log_error("len not match\n");
      }
      return 3;
  }

  if(keyvalue[0] != OTA_CONSULT_KEYVALUE_INFO_LENGTH){
      if(file_log_enable){
          DS_app_log_error("len not info len\n");
      }
      return 3;
  }

  data[0] = 0xfe;  //因为传参的时候没包含key
  memcpy(&data[1], keyvalue, len);

  setThisParam(ENbyOtaConSultKeyValue, (unsigned char *)data);
  consumption_confirm(); //组文件确认物模型
  creat_ota_wait_finish_event();

  iret = start_timer_to_trigger_confirm();
  if(iret){ //触发第二次握手失败，直接应答
      kv.id = 0xfd;
      kv.valueSize = OTA_CONFIRM_VALUE_LENGTH;
      getThisParam(ENbyOtaConfirmKeyValue, &kv.value);
      set_key_value(&kv);
      creat_ota_wait_finish_event();
  }

  start_timer_to_check_no_rcv_timeout();
  return 0;
}

int consumption_deal_file_updateme_keyvalue(const unsigned char *keyvalue, int len)
{
  if(!keyvalue || len == 0){
      return -1;
  }
  //UPDATEME物模型 ctrl id[]
  unsigned char rfmid = 0;
  unsigned char updateme_id_num = 0;
  unsigned char i = 0;
  unsigned char updateme_id[OTA_ID_BUF_MAX] = {0};
  FILE_TRANSPORT_E step;
  step = get_file_transport_step();
  if(step != CONSUMPTION_RECEVE && step != CONSUMPTION_FINISH_TRANSPORT){
      return 1;
  }

  if(keyvalue[0] == 0xf1){ //ctrl 0xf1,校验请求
      updateme_id_num = len - 1;
      if(updateme_id_num == 0){
          if(file_log_enable){
              DS_app_log_error("no id buf\n");
          }
          return 4;
      }else{
          if(updateme_id_num > OTA_ID_BUF_MAX){
              if(file_log_enable){
                  DS_app_log_error("id too much\n");
              }
              return 5;
          }
      }
      getThisParam(ENpbyRfmId, &rfmid);
      for(i = 0; i < updateme_id_num; i++){
          if(keyvalue[1+i] == rfmid){
              break;
          }
      }
      if(step == CONSUMPTION_RECEVE){
          if(i == updateme_id_num){
          //没有找到，可能被踢了，退出OTA
              creat_ota_abort_event();
          }else{
              memcpy(updateme_id, &keyvalue[1], updateme_id_num);
              setThisParam(ENbyOtaUpdatemeID, updateme_id);      //ota ID[]
              setThisParam(ENbyOtaUpdatemeIDNum, &updateme_id_num);     //ota ID长度
              creat_ota_rx_file_check_event();
              start_timer_to_check_no_rcv_timeout();
          }
      }else{ //CONSUMPTION_FINISH_TRANSPORT
          if(i == updateme_id_num){

          }else{
              memcpy(updateme_id, &keyvalue[1], updateme_id_num);
              setThisParam(ENbyOtaUpdatemeID, updateme_id);      //ota ID[]
              setThisParam(ENbyOtaUpdatemeIDNum, &updateme_id_num);     //ota ID长度
              creat_ota_rx_file_check_event();
              start_timer_to_check_no_rcv_timeout();
          }
      }
  }
  return 0;
}

int consumption_deal_file_payload(const unsigned char *payload, int len)
{
  (void)payload;
  (void)len;
  FILE_TRANSPORT_E step;
  step = get_file_transport_step();
  if(step != CONSUMPTION_RECEVE){
      return 1;
  }
  if(!filepayload_cache_to_file_link((unsigned char *)payload, len)){
      creat_ota_rx_file_page_event();
      start_timer_to_check_no_rcv_timeout();
  }else{
      if(file_log_enable){
          APP_PRINTF("cache error\r\n");
      }
  }
  return 0;
}
#endif
